#include <iostream>
#include <pthread.h>
#include <string>
#include <vector>
#include <stdio.h>
#include <unistd.h>
#include "LockGuard.hpp"
using namespace std;

// 1.创建多线程
// 2.验证资源共享
// 3.线程分离
// 4.模拟多线程抢票

// int g_val = 100;
// __thread int g_val = 100;
// int* p = nullptr;
// #define NUM 3
// struct ThreadData
// {
//     ThreadData(int number)
//     {
//         _threadname = "thread" + to_string(number);
//     }
//     string _threadname;
// };

// string toHex(pthread_t tid)
// {
//     char buffer[1024] = {0};
//     snprintf(buffer, sizeof(buffer), "0x%x", tid);
//     return buffer;
// }
// void* routine(void* arg)
// {
//     ThreadData* td = static_cast<ThreadData*> (arg);
//     string tid = toHex(pthread_self());
//     pthread_detach(pthread_self());
//     //int g_val = 100;
//     // int cnt = 5;
//     //if(td->_threadname == "thread1")  p = &g_val;
//     while(true)
//     {
//         printf("%s, pid:%d, tid:%s, g_val:%d, &g_val:%p\n", td->_threadname.c_str(), getpid(),  tid.c_str(),g_val, &g_val);
//         g_val--;
//         sleep(1);
//         // if(--cnt == 0)  break;
//     }

//     delete td;
//     return nullptr;
// }

// int main()
// {
//     vector<pthread_t> tids;
//     for(int i = 1; i <= NUM; i++)
//     {
//         pthread_t tid;
//         ThreadData* td = new ThreadData(i);
//         pthread_create(&tid, nullptr, routine, (void*)td);
//     }

//     sleep(1);
//     for(int i = 0; i < tids.size(); i++)
//     {
//         pthread_detach(tids[i]);
//     }
//     while(true)
//     {
//         // cout << "main thread" << endl;
//         printf("main thread, &p:%p\n", p);
//         sleep(1);
//     }
//     // for(auto td : tids)
//     // {
//     //     pthread_join(td, nullptr);
//     // }
//     return 0;
// }

#define NUM 4
int tickets = 100;
string toHex(pthread_t tid)
{
    char buffer[1024] = {0};
    snprintf(buffer, sizeof(buffer), "0x%x", tid);
    return buffer;
}
class ThreadData
{
public:
    // ThreadData(int number, pthread_mutex_t *lock)
    //     : _lock(lock)
    // {
    //     _name = "threat" + to_string(number);
    // }
    ThreadData(int number)
    {
        _name = "threat" + to_string(number);
    }
public:
    string _name;
    //pthread_mutex_t *_lock;
};

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
void *getTicket(void *arg)
{
    ThreadData *td = static_cast<ThreadData *>(arg);
    while (true)
    {
        {
            LockGuard lockguard(&lock);
            if (tickets > 0)
            {
                usleep(1000);
                tickets--;
                printf("%s get a ticket:%d\n", td->_name.c_str(), tickets);
            }
            else
            {
                break;
            }
        }
        usleep(13);
    }

    printf("%s quit........\n", td->_name.c_str());
}
// void *getTicket(void *arg)
// {
//     ThreadData *td = static_cast<ThreadData *>(arg);
//     while (true)
//     {
//         pthread_mutex_lock(td->_lock);
//         if (tickets > 0)
//         {
//             usleep(1000);
//             tickets--;
//             printf("%s get a ticket:%d\n", td->_name.c_str(), tickets);
//             pthread_mutex_unlock(td->_lock);
//         }
//         else
//         {
//             pthread_mutex_unlock(td->_lock);
//             break;
//         }
//         usleep(13);
//     }

//     printf("%s quit........\n", td->_name.c_str());
// }
int main()
{
    vector<pthread_t> tids;
    vector<ThreadData *> thread_datas;
    pthread_mutex_t lock;
    pthread_mutex_init(&lock, nullptr);
    for (int i = 1; i <= NUM; i++)
    {
        pthread_t tid;
        ThreadData *td = new ThreadData(i);
        pthread_create(&tid, nullptr, getTicket, (void *)td);
        tids.push_back(tid);
        thread_datas.push_back(td);
    }

    for (auto tid : tids)
    {
        pthread_join(tid, nullptr);
    }
    for (auto td : thread_datas)
    {
        delete td;
    }
    pthread_mutex_destroy(&lock);

    return 0;
}